package apis

import (
	"github.com/gin-gonic/gin"
	"tylnmall/models"
	"github.com/jinzhu/gorm"
	"common/logger"
	"net/http"
	"tylnmall/constant"
	"errors"
	"tylnmall/service"
	"math"
	"time"
	"strings"
	"fmt"
)

//总商品列表
func CommodityAllListApi(c *gin.Context) {
	type param struct {
		Page    int `json:"page" form:"page"`
		Orderby int `json:"orderby" form:"orderby"` //1.时间正序 2.时间逆序 3.价格正序 4.价格逆序
	}
	var p param
	var commoditys []*models.Commodity
	var err error
	if err = c.Bind(&p); err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}

	var ord = ""
	switch p.Orderby {
	case 1:
		ord = "updatetime DESC"
	case 2:
		ord = "updatetime ASC"
	case 3:
		ord = "unit_price DESC"
	case 4:
		ord = "unit_price ASC"
	default:
		ord = "id"
	}
	db := c.MustGet("ty").(*gorm.DB)
	var count float64
	if err := db.Model(&models.Commodity{}).Count(&count).Error; err != nil {
		logger.Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	if p.Page == 0 {
		p.Page = 1
	} else if float64(p.Page) > math.Ceil(count/15.0) {
		p.Page = 1
	}
	if err = db.Limit(15).Offset((p.Page - 1) * 15).Order(ord).Find(&commoditys).Error; err != nil {
		logger.Error(err)
		err = errors.New("story not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"list": commoditys, "pageNum": math.Ceil(count / 15.0), "CommodityNum": count})
}

//根据id 商品列表
func CommodityListByIdApi(c *gin.Context) {
	type param struct {
		Id      int `json:"id" form:"id"`
		Type    int `json:"type" form:"type"` //接口类别 0:根据商品id 1:根据商铺id 2:根据类别id
		Page    int `json:"page" form:"page"`
		Orderby int `json:"orderby" form:"orderby"` //1.时间正序 2.时间逆序 3.价格正序 4.价格逆序
	}
	var commoditys []*models.Commodity
	var err error
	var p param
	if err = c.Bind(&p); err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	db := c.MustGet("ty").(*gorm.DB)
	var str string
	switch p.Type {
	case 0:
		str = "id = ?"
	case 1:
		str = "story_id = ?"
	case 2:
		var spec []*models.CommoditySpecies
		if err = db.Where("father_id = ?", p.Id).Find(&spec).Error; err != nil {
			logger.Error(err)
			err = errors.New("species not found")
			logger.Error(err)

		}
		var ord = ""
		switch p.Orderby {
		case 1:
			ord = "updatetime DESC"
		case 2:
			ord = "updatetime ASC"
		case 3:
			ord = "unit_price DESC"
		case 4:
			ord = "unit_price ASC"
		default:
			ord = "id"
		}
		if len(spec) == 0 {
			str = "commodity_species_id = ?"
		}
		str = "commodity_species_id = ? or commodity_species_id in (?)"
		var l []int
		for _, s := range spec {
			l = append(l, s.Id)
		}
		var count float64
		if err := db.Where(str, p.Id, l).Model(&models.Commodity{}).Count(&count).Error; err != nil {
			logger.Error(err)
			c.AbortWithStatus(http.StatusInternalServerError)
			return
		}
		if p.Page == 0 {
			p.Page = 1
		} else if float64(p.Page) > math.Ceil(count/15.0) {
			p.Page = 1
		}
		if err = db.Limit(15).Offset((p.Page - 1) * 15).Order(ord).Where(str, p.Id, l).Find(&commoditys).Error; err != nil {
			logger.Error(err)
			err = errors.New("commodity not found")
			logger.Error(err)
			c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
			return
		}
		c.JSON(http.StatusOK, gin.H{"list": commoditys, "pageNum": math.Ceil(count / 15.0), "CommodityNum": count})
		return
	}

	if err = db.Where(str, p.Id).Find(&commoditys).Error; err != nil {
		logger.Error(err)
		err = errors.New("commodity not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"list": commoditys})
}

//根据名称获取商品列表
func CommodityListByNameApi(c *gin.Context) {
	type param struct {
		Name    string `json:"name" form:"name"`
		Page    int    `json:"page" form:"page"`
		Orderby int    `json:"orderby" form:"orderby"` //1.时间正序 2.时间逆序 3.价格正序 4.价格逆序
	}
	var commoditys []*models.Commodity
	var err error
	var p param
	if err = c.Bind(&p); err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	var ord = ""
	switch p.Orderby {
	case 1:
		ord = "updatetime DESC"
	case 2:
		ord = "updatetime ASC"
	case 3:
		ord = "unit_price DESC"
	case 4:
		ord = "unit_price ASC"
	default:
		ord = "id"
	}
	db := c.MustGet("ty").(*gorm.DB)
	var count float64
	if err := db.Where("name like ?", "%"+p.Name+"%").Model(&models.Commodity{}).Count(&count).Error; err != nil {
		logger.Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	if p.Page == 0 {
		p.Page = 1
	} else if float64(p.Page) > math.Ceil(count/15.0) {
		p.Page = 1
	}
	if err = db.Limit(15).Offset((p.Page - 1) * 15).Order(ord).Where("name like ?", "%"+p.Name+"%").Find(&commoditys).Error; err != nil {
		logger.Error(err)
		err = errors.New("commodity not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"list": commoditys, "pageNum": math.Ceil(count / 15.0), "CommodityNum": count})
}

//商品父类分类列表
func SpeciesFatherListApi(c *gin.Context) {
	//type param struct {
	//	Id int `json:"id"`
	//	Name string `json:"id"`
	//	p []*param `json:"p"`
	//}
	type param struct {
		Id       int    `json:"id" form:"id"`
		Name     string `json:"name" form:"name"`           //类别名称
		FatherId int    `json:"father_id" form:"father_id"` //父类id
	}
	var first []*models.CommoditySpecies
	var err error
	db := c.MustGet("ty").(*gorm.DB)
	if err = db.Where("father_id = 0").Find(&first).Error; err != nil {
		logger.Error(err)
		err = errors.New("species not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	var list []*param
	for _, f := range first {
		var p param
		p.Id = f.Id
		p.Name = f.Name
		p.FatherId = f.FatherId
		list = append(list, &p)
	}
	c.JSON(http.StatusOK, gin.H{"list": list})

}

//商品子类分类列表
func SpeciesChildListApi(c *gin.Context) {
	type param struct {
		Id int `json:"id" form:"id"`
	}
	var p param
	var err error
	var first []*models.CommoditySpecies
	var spec []*service.SpeciesList
	db := c.MustGet("ty").(*gorm.DB)
	if err = c.Bind(&p); err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	if err = db.Where("father_id = ?", p.Id).Find(&first).Error; err != nil {
		logger.Error(err)
		err = errors.New("species not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	for _, f := range first {
		var s service.SpeciesList
		s.Id = f.Id
		s.Name = f.Name
		spec = append(spec, &s)
	}
	if err, spec = service.SpeciesChildList(db, spec); err != nil {
		logger.Error(err)
		err = errors.New("species not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"list": spec})
}

//商品分类根据id查询
func SpeciesByIdApi(c *gin.Context) {
	type param struct {
		Id int `json:"id" form:"id"`
	}
	var p param
	var err error
	if err = c.Bind(&p); err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	var spec models.CommoditySpecies
	db := c.MustGet("ty").(*gorm.DB)
	if err = db.Where("id = ?", p.Id).Find(&spec).Error; err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"Species": spec})
}

func HotSellListApi(c *gin.Context) {
	var commodity []*models.Commodity
	var hotsell []*models.HotSell
	var err error
	db := c.MustGet("ty").(*gorm.DB)
	if err = db.Find(&hotsell).Error; err != nil {
		logger.Error(err)
		err = errors.New("hotsell not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	var list []int
	for _, f := range hotsell {
		list = append(list, f.CommodityId)
	}
	if err = db.Where("id in (?)", list).Find(&commodity).Error; err != nil {
		logger.Error(err)
		err = errors.New("hotsell not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"list": commodity})
}

//新增商品
func CommodityAddApi(c *gin.Context) {
	var commodity models.Commodity
	var err error
	if err = c.Bind(&commodity); err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	const base_format = "2006-01-02 15:04:05"
	//获取当前时间
	nt := time.Now()
	var timeStr = nt.Format(base_format)
	commodity.Createtime = timeStr
	commodity.Updatetime = timeStr
	var errorMsg string
	if commodity.Name == "" {
		errorMsg = "name is null"
	} else if commodity.Type == 0 {
		errorMsg = "type is null"
	} else if commodity.Image == "" {
		errorMsg = "image is null"
	} else if commodity.UnitPrice == 0 {
		errorMsg = "price is null"
	} else if commodity.CommoditySpeciesId == 0 {
		errorMsg = "Species is null"
	} else if commodity.StoryId == 0 {
		errorMsg = "story is null"
	}else if commodity.Details == "" {
		errorMsg = "Details is null"
	}else if commodity.Service == ""{
		errorMsg = "Service is null"

	}
	if errorMsg != "" {
		err = errors.New(errorMsg)
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	db := c.MustGet("ty").(*gorm.DB)
	if err = db.Create(&commodity).Error; err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": "success"})
}

//删除商品
func CommodityDeleteApi(c *gin.Context) {
	type param struct {
		Id int `json:"id" form:"id"`
	}
	var p param
	var err error
	if err = c.Bind(&p); err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	db := c.MustGet("ty").(*gorm.DB)
	b, commodity := service.IsCommodity(db, p.Id)
	if !b {
		err = errors.New("commodity is not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	if err = db.Delete(&commodity).Error; err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": "success"})

}

//批量删除商品
func CommodityDeleteListApi(c *gin.Context) {
	type param struct {
		Ids string `json:"ids" form:"ids"`
	}
	var p param
	var err error
	var list []string
	var commodity models.Commodity
	if err = c.Bind(&p); err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	list = strings.Split(p.Ids, ",")
	fmt.Println(list)
	if len(list) <= 0 {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	db := c.MustGet("ty").(*gorm.DB)
	if err = db.Where("id in (?)", list).Delete(&commodity).Error; err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": "success"})
}

//修改商品
func CommodityUpdateApi(c *gin.Context) {
	type param struct {
		Id                 int     `json:"id" form:"id"`
		Name               string  `json:"name" form:"name"`                                 //商品名称
		Introduce          string  `json:"introduce" form:"introduce"`                       //商品描述
		UnitPrice          float32 `json:"unit_price" form:"unit_price"`                     //单价
		Image              string  `json:"image" form:"image"`                               //图片
		Classification     int     `json:"classification" form:"classification"`             //类别
		Type               int     `json:"type" form:"type"`                                 //商品状态（0.停止销售；1.正在销售）
		StoryId            int     `json:"story_id" form:"story_id"`                         //所属商铺
		CommoditySpeciesId int     `json:"commodity_species_id" form:"commodity_species_id"` //商品类别
		Details            string  `json:"details" form:"details"`                           //详情
		Service            string  `json:"service" form:"service"`                           //售后服务

	}
	var p param
	var err error
	var commdity models.Commodity
	var b bool
	if err = c.Bind(&p); err != nil {
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	//if p.Id==0{
	//	c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
	//	return
	//}
	//commdity.Id = p.Id
	db := c.MustGet("ty").(*gorm.DB)
	if b, commdity = service.IsCommodity(db, p.Id); !b {
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorParamWrong, "err_msg": constant.TranslateErrCode(constant.ErrorParamWrong)})
		return
	}
	if p.Name != "" {
		commdity.Name = p.Name
	}
	if p.Introduce != "" {
		commdity.Introduce = p.Introduce
	}
	if p.UnitPrice != 0 {
		commdity.UnitPrice = p.UnitPrice
	}
	if p.Image != "" {
		commdity.Image = p.Image
	}
	//if p.Classification != 0{
	//	commdity.Classification = p.Classification
	//}
	if p.Type == 1 || p.Type == 0 {
		commdity.Type = p.Type
	}
	if p.StoryId != 0 {
		commdity.StoryId = p.StoryId
	}
	if p.CommoditySpeciesId != 0 {
		commdity.CommoditySpeciesId = p.CommoditySpeciesId
	}
	if p.Details != ""{
		commdity.Details = p.Details
	}
	if p.Service != ""{
		commdity.Service = p.Service
	}
	if err = db.Model(&commdity).Update(&p).Error; err != nil {
		logger.Error(err)
		err = errors.New("commdity not found")
		logger.Error(err)
		c.JSON(http.StatusOK, gin.H{"err_code": constant.ErrorDB, "err_msg": constant.TranslateErrCode(constant.ErrorDB)})
		return
	}
	c.JSON(http.StatusOK, gin.H{"commdity": commdity, "status": "success"})
}
